package com.ak.game.netty;

import com.ak.game.entity.PnGameTwistRecord;
import com.ak.game.entity.vo.BetReqVo;
import com.ak.game.service.BettingService;
import com.ak.game.service.RemoteWebSocketClientService;
import com.ak.game.util.AjaxResult;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.AttributeKey;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

@Slf4j
public class WebSocketFrameHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

    private final String gameId;

    private final RemoteWebSocketClientService clientService;

    private final BettingService bettingService;

    private ChannelHandlerContext ctx;

    public WebSocketFrameHandler(String gameId, RemoteWebSocketClientService clientService, BettingService bettingService) {
        this.bettingService = bettingService;
        this.gameId = gameId;
        this.clientService = clientService;
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        this.ctx = ctx;
        super.channelActive(ctx);
    }

    /**
     * 重写SimpleChannelInboundHandler的channelRead0方法，处理接收到的消息
     *
     * @param ctx the {@link ChannelHandlerContext} which this {@link SimpleChannelInboundHandler}
     *            belongs to
     * @param msg the message to handle
     */
    @Override
    public void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) {
        String text = msg.text();
        JSONObject jsonObject = JSONObject.parseObject(text);
        String msgId = jsonObject.getString("msg_id");
        Map<String, List<String>> params = (Map<String, List<String>>) ctx.channel().attr(AttributeKey.valueOf("params")).get();
        String userId = params.get("user_id").get(0);
        switch (msgId) {
            // 下注请求
            case "1001":
                log.info("收到msg_id=1001下注请求，请求参数={}", text);
                String timestamp = String.valueOf(System.currentTimeMillis());
                BetReqVo betReqVo = new BetReqVo();
                Map<String, Object> data1001 = new HashMap<>();
                data1001.put("user_id", userId);
                data1001.put("amount", jsonObject.get("amount"));
                data1001.put("multiple", 1);
                betReqVo.setData(data1001);
                Map<String, Object> game1001 = new HashMap<>();
                game1001.put("id", gameId);
                game1001.put("round_id", timestamp);
                game1001.put("start_time", timestamp);
                betReqVo.setGame(game1001);
                CompletableFuture<Object> objectCompletableFuture = clientService.sendMessage(JSON.toJSONString(betReqVo));
                try {
                    Object result = objectCompletableFuture.get(10, TimeUnit.SECONDS);
                    AjaxResult ajaxResult = (AjaxResult) result;
                    // 如果接口api返回的code=200，则走游戏业务逻辑
                    if (ajaxResult.getCode() == 200) {
                        ajaxResult.setMsg_id("1001");
                        // 插入user_money_session表的数据
                        Integer betResult = bettingService.bet(betReqVo);
                        List<PnGameTwistRecord> pnGameTwistRecords = bettingService.selectAllTwistRecord(betReqVo);
                        // 返回数据给前端
                        ctx.channel().writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(ajaxResult.setData(Map.of("result", betResult, "data", pnGameTwistRecords)))));
                        // 返回数据给接口api端

                    } else {
                        // 返回数据给前端
                        ajaxResult.setMsg_id("1001");
                        ctx.channel().writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(ajaxResult)));
                        log.info("下注请求成功：msg_id 1001 ---- 返回结果={}", JSON.toJSONString(ajaxResult));
                    }
                } catch (Exception e) {
                    if (e.getMessage().equals("10009")) {
                        ctx.channel().writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(AjaxResult.fail("10009"))));
                    }
                }
                break;
            // 部分结算
            case "1002":
                log.info("收到msg_id=1002部分结算请求，请求参数={}", text);
                try {
                    bettingService.cashPartial(userId);
                    ctx.channel().writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(AjaxResult.success("success", "1002"))));
                    log.info("部分结算请求成功：msg_id=1002 ---- 返回结果={}", JSON.toJSONString(AjaxResult.success("success", "1002")));
                } catch (Exception e) {
                    ctx.channel().writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(AjaxResult.fail("10004"))));
                }
                break;
            // 全部结算
            case "1003":
                log.info("收到msg_id=1003全部结算请求，请求参数={}", text);
                try {
                    bettingService.cashAll(userId);
                    ctx.channel().writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(AjaxResult.success("success", "1003"))));
                    log.info("全部结算请求成功：msg_id=1003 ---- 返回结果={}", JSON.toJSONString(AjaxResult.success("success", "1003")));
                } catch (Exception e) {
                    ctx.channel().writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(AjaxResult.fail("10004"))));
                }
                break;
        }
    }

    /**
     * 管道异常处理，防止资源泄露
     *
     * @param ctx   通道代理上下文
     * @param cause 异常
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        String userId = ctx.channel().attr(AttributeKey.valueOf("userId")).get().toString();
        RemoteWebSocketClientService.FUTURES.remove(userId);
        log.error("连接失败：{}", cause.getMessage()); // 记录日志
        ctx.close(); // 关闭发生异常的通道，防止资源泄露
    }


}
